from utils.key import is_valid_redis_key, get_all_keys
from redisData.rServer import RS
# 存放list的键值

def check_list_key(list_key,rClient):
    all_keys=get_all_keys(rClient)
    if list_key in all_keys:
        if all_keys[list_key]!="list":
            return  "(error) WRONGTYPE Operation against a key holding the wrong kind of value"

            
def lpush(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key): 
            cmd_list.pop(0)
            check_list_key(key,rClient)
            if key not in all_keys:
                list_data[key]=[]
                for element in cmd_list:
                    list_data[key].insert(0,element)
                return "(integer)"+str(len(list_data[key]))
            else :
                for element in cmd_list:
                    list_data[key].insert(0,element)
                return  "(integer)"+str(len(list_data[key]))
        else:
            return "(error) Invalid key"
    else :
        return "(error) ERR wrong number of arguments for 'lpush' command   "

def lpushx(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            cmd_list.pop(0)
            if key in all_keys:
                for element in cmd_list:
                    list_data[key].insert(0,element)
                return "(integer)"+str(len(list_data[key]))
            else:
                return "(integer) 0"
        else:
            return "(error) Invalid key"
    else :
        return "(error) ERR wrong number of arguments for 'lpushx' command   "

def rpush(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        cmd_list.pop(0)
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            if key not in all_keys:
                list_data[key]=[]
                list_data[key].extend(cmd_list)
                return "(integer)"+str(len(list_data[key]))
            else :
                list_data[key].extend(cmd_list)
                return  "(integer)"+str(len(list_data[key]))
        else:
            return "(error) Invalid key"
    else :
        return "(error) ERR wrong number of arguments for 'rpush' command   "


def rpushx(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            cmd_list.pop(0)
            if key in all_keys:
                list_data[key].extend(cmd_list)
                return "(integer)"+str(len(list_data[key]))
            else:
                return "(integer) 0"
        else:
            return "(error) Invalid key"
    else :
        return "(error) ERR wrong number of arguments for 'rpushx' command   "

def lpop(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            cmd_list.pop(0)
            count=int(cmd_list[0])
            if key in all_keys:
                values=[]
                while count > 0 and list_data[key]:
                    values.append(list_data[key].pop(0))
                    count -= 1
                return str(values)
            else:
                return "(nil)"
        else:
            return "(error) Invalid key"
    else:
        return "(error) ERR wrong number of arguments for 'lpop' command   "



def rpop(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)>=2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            cmd_list.pop(0)
            count=int(cmd_list[0])
            if key in all_keys:
                values=[]
                while count > 0 and list_data[key]:
                    values.append(list_data[key].pop())
                    count -= 1
                return str(values)
            else:
                return "(nil)"
        else:
            return "(error) Invalid key"
    else:
        return "(error) ERR wrong number of arguments for 'rpop' command   "

def rpoplpush(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==2:
        all_keys=get_all_keys(rClient)
        key=cmd_list[0]
        if is_valid_redis_key(key):
            check_list_key(key,rClient)
            key2=cmd_list[1]
            if key in all_keys:
                if key2 in all_keys:
                    element=list_data[key].pop()
                    list_data[key2].insert(0,element)
                    return str(element)
                else:
                    list_data[key2]=[]
                    element=list_data[key].pop()
                    list_data[key2].insert(0,element)
                    return str(element)
            else:
                return "(nil)"
        else:
            return "(error) Invalid key"
    else :
        return  "(error) ERR wrong number of arguments for 'rpoplpush' command   "

def lrem(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==3:
        key=cmd_list[0]
        cmd_list.pop(0)
        all_keys=get_all_keys(rClient)
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            if key in all_keys:
                rmovecount=0
                count=int(cmd_list[0])
                cmd_list.pop(0)
                element=cmd_list[0]
                while element in list_data[key] and rmovecount<count:
                    list_data[key].remove(element)
                    rmovecount+=1
                return str(rmovecount)
            else:
                return "(integer) 0"
        else:
            return  "(error) Invalid key"
    else:
        return"(error) ERR wrong number of arguments for 'lrem' command   "

def llen(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==1:
        key=cmd_list[0]
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            all_keys=get_all_keys(rClient)
            if key in all_keys:
                return str(len(list_data[key]))
            else:
                return "(integer) 0"
        else:
            return  "(error) Invalid key"
        
    else:
        return "(error) ERR wrong number of arguments for 'llen' command   "

def lindex(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==2:
        key=cmd_list[0]
        cmd_list.pop(0)
        index=int(cmd_list[0])
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            all_keys=get_all_keys(rClient)
            if key in all_keys:
                if index<=len(list_data[key]):
                    return str(list_data[key][index])
                else:
                    return "(nil)"
            else:
                return "(nil)"
        else:
            return  "(error) Invalid key"
        
    else:
        return "(error) ERR wrong number of arguments for 'llen' command   "

def lset(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==3:
        key=cmd_list[0]
        cmd_list.pop(0)
        index=int(cmd_list[0])
        element=cmd_list[1]
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            all_keys=get_all_keys(rClient)
            if key in all_keys:
                if index<=len(list_data[key]):
                    list_data[key][index]=element
                    return "OK"
                else:
                    return "(error) ERR index out of range "
            else:
                return "(error) ERR no such key  "
        else:
            return  "(error) Invalid key"
        
    else:
        return "(error) ERR wrong number of arguments for 'lset' command   "


def lrange(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==3:
        key=cmd_list[0]
        cmd_list.pop(0)
        start=int(cmd_list[0])
        end=int(cmd_list[1])
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            all_keys=get_all_keys(rClient)
            if key in all_keys:
                if start<=len(list_data[key]) and start<=end:
                    return ' '.join(map(str, list_data[key][start:end]))
                else:
                    return "(empty list or set)  "
                    
            else:
                return "(empty list or set)  "
        else:
            return  "(error) Invalid key"
    
    else:
        return "(error) ERR wrong number of arguments for 'lrange' command   "
    
    
def ltrim(cmd_list,rClient):
    list_data=RS.rDB[rClient.redisDbId].list_data
    cmd_list.pop(0)
    if len(cmd_list)==3:
        key=cmd_list[0]
        cmd_list.pop(0)
        start=int(cmd_list[0])
        end=int(cmd_list[1])
        check_list_key(key,rClient)
        if is_valid_redis_key(key):
            all_keys=get_all_keys(rClient)
            if key in all_keys:    
                list_data[key]=list_data[key][start:end]
                return "OK"          
            else:
                return "(empty list or set)  "
        else:
            return  "(error) Invalid key"
    
    else:
        return "(error) ERR wrong number of arguments for 'ltrim' command   "

    
    
    
    
    